package com.glela.common.aspect;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.glela.firewall.beans.FirewallLog;
import com.glela.firewall.service.FirewallService;
import com.glela.platform.constant.ErrorEnum;
import com.glela.platform.model.request.RequestBaseModel;
import com.glela.platform.model.request.RequestParamForSecurity;
import com.glela.platform.model.response.ResponseBaseModel;
import com.glela.platform.util.SecurityStringUtils;

@Aspect
@Component
@Order(1)
public class FirewallAspect {

    private static Logger logger = LoggerFactory.getLogger(FirewallAspect.class);

    @Autowired
    private FirewallService firewallService;

    @Around("execution(* com.glela.controller.*.*(..))")
    public Object around(ProceedingJoinPoint pjp) {
//        long begin = System.currentTimeMillis();
        boolean result = true;
        String guestId = "";
        try {
            Object[] args = pjp.getArgs();
            if (args != null && args.length > 0) {
                for (Object arg : args) {
                    if (arg instanceof RequestBaseModel) {
                        guestId = ((RequestBaseModel) arg).getGuestId();
                    } else if (arg instanceof RequestParamForSecurity) {
                        guestId = ((RequestParamForSecurity) arg).getGuestId();
                    } else if (arg instanceof RequestBaseModel) {
                        guestId = ((RequestBaseModel) arg).getGuestId();
                    }
                }
            }
            if (StringUtils.isNotBlank(guestId)) {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                        .getRequestAttributes()).getRequest();
                String ip = SecurityStringUtils.getRemoteAddress(request);
                String url = request.getRequestURI();
                String userAgent = request.getHeader("user-agent");
                String channel = request.getHeader("channel");
                String platform = request.getHeader("platform");
                FirewallLog firewallLog = new FirewallLog();
                firewallLog.setIp(ip);
                firewallLog.setUrl(url);
                firewallLog.setAgent(getAgent(userAgent));
                firewallLog.setGuestId(guestId);
                firewallLog.setPlatform(platform);
                firewallLog.setChannel(channel);
                result = firewallService.check(firewallLog);
            }
        } catch (Exception e) {
            logger.error("接口防火墙处理异常，允许通过", e);
        }
//        logger.info("防火墙拦截耗时：" + (System.currentTimeMillis() - begin));
        if (result) {
            try {
                return pjp.proceed();
            } catch (Throwable e) {
                logger.error(e.getMessage(), e);
                return new ResponseEntity<>(new ResponseBaseModel(ErrorEnum.C20000), HttpStatus.OK);
            }
        } else {
            return new ResponseEntity<>(new ResponseBaseModel(ErrorEnum.C20000), HttpStatus.METHOD_NOT_ALLOWED);
        }
    }

    private String getAgent(String userAgent) {
        if (StringUtils.isNotBlank(userAgent)) {
            if (userAgent.length() >= 20) {
                return userAgent.substring(0, 20);
            } else return userAgent;
        } else return "";
    }
}
